/*****************************************************************************
 * Copyright (C) Stacy Curl. All rights reserved.                            *
 * ------------------------------------------------------------------------- *
 * The software in this package is published under the terms of the BSD      *
 * style license a copy of which has been included with this distribution in *
 * the LICENSE.txt file.                                                     *
 *****************************************************************************/
package picounit.features.base;

import picounit.Marker;
import picounit.PicoUnitAPI;
import picounit.Registry;
import picounit.TestFilter;
import junit.framework.Test;

public class PicoUnitImpl implements PicoUnitAPI {
	public PicoUnitImpl(String name, Marker marker) {
		this.name = name;
		this.marker = marker;

		FeatureResolver featureResolver = new FeatureLoader(name).loadFeatures();

		this.registry = featureResolver.getFeature(Registry.class);
		this.testFinder = featureResolver.getFeature(TestFinder.class);
	}

	///////////////////////////////////////////////////////////////////////////////////////////////
	// PicoUnitAPI methods
	///////////////////////////////////////////////////////////////////////////////////////////////

	public Test generateJUnitTest() {
		return generateJUnitTest(new Caller(STACK_DISTANCE_TO_CALLER).callingClass());
	}

	public Test generateJUnitTest(Class<?> startingClass) {
		return generateJUnitTest(startingClass, new AlwaysPassingTestFilter());
	}

	public Test generateSingleJUnitTest(Class<?> testClass) {
		return generateJUnitTest(testClass, new SingleTestTestFilter(testClass.getName()));
	}

	public Test generateJUnitTest(Class<?> startingClass, TestFilter testFilter) {
		return testFinder.findTests(name, startingClass, marker, testFilter);
	}

	public <B, D extends B> void register(Class<B> type, D instance) {
		registry.register(type, instance);
	}

	public <B, D extends B> void register(Class<B> type, Class<D> implementation) {
		registry.register(type, implementation);
	}

	public void register(Class<?> implementation) {
		registry.register(implementation);
	}

	public void register(String key, boolean value) {
		registry.register(key, value);
	}

	public void register(String key, byte value) {
		registry.register(key, value);
	}

	public void register(String key, char value) {
		registry.register(key, value);
	}

	public void register(String key, double value) {
		registry.register(key, value);
	}

	public void register(String key, float value) {
		registry.register(key, value);
	}

	public void register(String key, int value) {
		registry.register(key, value);
	}

	public void register(String key, long value) {
		registry.register(key, value);
	}

	public void register(String key, short value) {
		registry.register(key, value);
	}

	public void register(String key, String value) {
		registry.register(key, value);
	}
	
	public <B> ImplementationCapturer<B> registerFactory(Class<B> type) {
		return registry.registerFactory(type);
	}

	///////////////////////////////////////////////////////////////////////////////////////////////
	// Implementation
	///////////////////////////////////////////////////////////////////////////////////////////////

	private final String name;
	private final Marker marker;

	private final Registry registry;
	private final TestFinder testFinder;

	private static final int STACK_DISTANCE_TO_CALLER = 2;
}
